04 / 04

How does Go's error model differ from exceptions in other languages?

Go treats errors as values returned explicitly from functions. There are no exceptions, no implicit control flow jumps, and no try/catch — every error must be handled or explicitly ignored at the call site.

In languages like Java or Python, exceptions can propagate invisibly up the call stack until caught. In Go, errors are plain values returned as a second return value. The caller must decide what to do — there are no surprise control flow jumps.

Go error model basics
Benefits and trade-offs
  1. 1

    Error paths are explicit and visible in code — no hidden control flow

  2. 2

    Errors are traceable: wrapping with %w preserves the chain for errors.Is/As

  3. 3

    Encourages thinking about failure modes at every call site

  4. 4

    Trade-off: more boilerplate — the if err != nil pattern is repetitive

  5. 5

    No checked vs unchecked exception distinction — all errors are the same type

Difficulty: 6/10
Topics: error handling, exception vs error, propagation

Scenario Questions

0-2 years experience
  1. 1

    You need to read a configuration file and return its contents. How would you handle a failure to open the file using Go's error model instead of throwing an exception?

  2. 2

    If a function you call returns an error, what steps do you take to propagate that error up to the caller?

  3. 3

    What happens if you ignore the error value returned by a Go function? How does that differ from catching an exception in Java?

2-5 years experience
  1. 1

    You are adding a new HTTP endpoint that calls several downstream services. How would you design the error handling flow in Go, and why might you prefer explicit error returns over panic/recover?

  2. 2

    During debugging you notice a panic being recovered deep in the call stack, masking the original error. How would you refactor the code to use Go's error values for better observability?

  3. 3

    When integrating a Go library that uses panic for control flow, what trade‑offs do you consider when wrapping it to fit Go's idiomatic error handling?

5-8 years experience
  1. 1

    In a high‑throughput microservice, you need to decide between returning errors as values or using panic/recover for unexpected conditions. What are the performance and reliability implications of each approach at scale?

  2. 2

    Design a reusable error‑handling middleware for a Go HTTP server that captures errors from handlers and translates them into appropriate HTTP responses. How does this differ from exception‑handling middleware in Java or Node.js?

  3. 3

    Your team is migrating a legacy codebase from a language with exceptions to Go. What strategies would you employ to systematically replace try/catch blocks with Go's error handling while preserving behavior and test coverage?

8+ years experience
  1. 1

    At an organization‑wide level you need to define a standard error handling policy for all Go services. How would you structure error types, wrapping, and logging to ensure consistency across teams, and what challenges does this address compared to exception hierarchies?

  2. 2

    When introducing a new cross‑service protocol, you must decide how to surface errors to clients. How would you design the error model—including codes, messages, and propagation—to balance Go's explicit errors with a unified API contract across services written in different languages?

  3. 3

    If you were to build a tool that automatically converts exception‑based code (e.g., Java) to Go, what architectural considerations around error handling would you need to account for to avoid semantic mismatches?

Follow-up Questions

  • Can you show how you would use errors.Is or errors.As to inspect a wrapped error?
  • When would you choose panic over returning an error in a library you write?
  • How does Go's approach affect the way you write unit tests for error paths?